//
//  PemExtension.swift
//  JKTools
//
//  Created by 姜奎 on 2024/11/4.
//

import Foundation
import SwiftJWT

struct P8Pem {

    private struct P8Claims: Claims {

        var iss: String
        var iat: Int
        var exp: Int
        var sub: String

        init(iss: String, iat: Int, exp: Int, sub: String) {
            self.iss = iss
            self.iat = iat
            self.exp = exp
            self.sub = sub
        }
    }

    let path: String

    let keyID: String

    let teamID: String

    func generatePushToken(bundleID: String, exp: TimeInterval = 1200) throws -> String {
        // 读取私钥文件
        let privateKeyData = try Data(contentsOf: URL(fileURLWithPath: path))
        let privateKeyString = String(data: privateKeyData, encoding: .utf8) ?? ""

        let pemContent = privateKeyString.replacingOccurrences(of: "-----BEGIN PRIVATE KEY-----", with: "")
            .replacingOccurrences(of: "-----END PRIVATE KEY-----", with: "")
            .replacingOccurrences(of: "-----BEGIN EC PRIVATE KEY-----", with: "")
            .replacingOccurrences(of: "-----END EC PRIVATE KEY-----", with: "")
            .replacingOccurrences(of: "\n", with: "")
            .trimmingCharacters(in: .whitespacesAndNewlines)

        let bytes = Data(base64Encoded: pemContent)!

        let myHeader = Header(kid: keyID)

        let myClaims = P8Claims(iss: teamID, iat: Int(Date().timeIntervalSince1970), exp: Int(Date().addingTimeInterval(60 * 60).timeIntervalSince1970), sub: bundleID)


        var a = JWT(header: myHeader, claims: myClaims)
        let token = try a.sign(using: .es256(privateKey: bytes))
        return token
    }
}

extension Data {
    func base64UrlEncodedString() -> String {
        return self.base64EncodedString()
            .replacingOccurrences(of: "+", with: "-")
            .replacingOccurrences(of: "/", with: "_")
            .replacingOccurrences(of: "=", with: "")
    }
}


extension URLSession {
    static func post(payload: String, token:String, topic: String = "", priority: Int, collapseID: String, payloadType: String, inSandbox: Bool) async throws -> (Data, URLResponse) {

        let url = "https://api\(inSandbox ? ".sandbox" : "").push.apple.com/3/device/\(token)"

        var request = URLRequest(url: URL(string: url)!)

        request.httpMethod = "POST"

        request.httpBody = payload.data(using: .utf8)

        if !topic.isEmpty {
            request.addValue(topic, forHTTPHeaderField: "apns-topic")
        }

        if !collapseID.isEmpty {
            request.addValue(topic, forHTTPHeaderField: "apns-collapse-id")
        }

        request.addValue("\(priority)", forHTTPHeaderField: "apns-priority")

        request.addValue(payloadType, forHTTPHeaderField: "apns-push-type")


        let session = URLSession(configuration: .default, delegate: NetworkProvider(), delegateQueue: .main)

        return try await session.data(for: request)
    }
}

class NetworkProvider: NSObject, URLSessionDelegate {

    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        completionHandler(.performDefaultHandling, nil)
    }
}

